<?php

namespace App\Http\Controllers\API;

use App\Http\Requests\API\CreateItemAPIRequest;
use App\Http\Requests\API\UpdateItemAPIRequest;
use App\Http\Requests\API\CreateItemManagerAPIRequest;
use App\Models\Item;
use App\Models\Cooperation;
use App\Repositories\ItemRepository;
use App\Repositories\ItemOrderRepository;
use App\Repositories\ItemManagerRepository;
use App\Repositories\ChannelRepository;
use App\Repositories\WechatUserRepository;
use App\Repositories\CooperationRepository;
use Illuminate\Http\Request;
use App\Http\Controllers\AppBaseController;
use InfyOm\Generator\Criteria\LimitOffsetCriteria;
use Prettus\Repository\Criteria\RequestCriteria;
use Response;

/**
 * Class ItemController
 * @package App\Http\Controllers\API
 */

class ItemAPIController extends AppBaseController
{
    /** @var  ItemRepository */
    private $itemRepository;

    public function __construct(ItemRepository $itemRepo)
    {
        $this->itemRepository = $itemRepo;
    }

    /**
     * @param Request $request
     * @return Response
     *
     * @SWG\Get(
     *      path="/items",
     *      summary="Get a listing of the Items.",
     *      tags={"Item"},
     *      description="Get all Items",
     *      produces={"application/json"},
     *      @SWG\Response(
     *          response=200,
     *          description="successful operation",
     *          @SWG\Schema(
     *              type="object",
     *              @SWG\Property(
     *                  property="success",
     *                  type="boolean"
     *              ),
     *              @SWG\Property(
     *                  property="data",
     *                  type="array",
     *                  @SWG\Items(ref="#/definitions/Item")
     *              ),
     *              @SWG\Property(
     *                  property="message",
     *                  type="string"
     *              )
     *          )
     *      )
     * )
     */
    public function index(Request $request)
    {
        $this->itemRepository->pushCriteria(new RequestCriteria($request));
        $this->itemRepository->pushCriteria(new LimitOffsetCriteria($request));
        $items = $this->itemRepository->orderBy('id', 'desc')->simplePaginate($request->input('limit', 20));

        return $this->sendResponse($items->toArray(), trans('flash.api.retrieve_success', ['model' => 'Items']));
    }

    /**
     * @param CreateItemAPIRequest $request
     * @return Response
     *
     * @SWG\Post(
     *      path="/items",
     *      summary="Store a newly created Item in storage",
     *      tags={"Item"},
     *      description="Store Item",
     *      produces={"application/json"},
     *      @SWG\Parameter(
     *          name="body",
     *          in="body",
     *          description="Item that should be stored",
     *          required=false,
     *          @SWG\Schema(ref="#/definitions/Item")
     *      ),
     *      @SWG\Response(
     *          response=200,
     *          description="successful operation",
     *          @SWG\Schema(
     *              type="object",
     *              @SWG\Property(
     *                  property="success",
     *                  type="boolean"
     *              ),
     *              @SWG\Property(
     *                  property="data",
     *                  ref="#/definitions/Item"
     *              ),
     *              @SWG\Property(
     *                  property="message",
     *                  type="string"
     *              )
     *          )
     *      )
     * )
     */
    public function store(CreateItemAPIRequest $request)
    {
        $input = $request->all();
        if (! fileUrlExists($input['logo']))
        {
            return $this->sendError('图片不存在');
        }

        if (empty($input['contracts']) || ! is_array($input['contracts']) || empty($input['contract']))
        {
            return $this->sendError('请上传合同');
        }
        else
        {
            if (! fileUrlExists($input['contract']))
            {
                return $this->sendError('合同 PDF 不存在');
            }

            foreach ($input['contracts'] as $val)
            {
                if (! fileUrlExists($val['photo']))
                {
                    return $this->sendError('合同图片不存在');
                }
            }
        }

        $items = $this->itemRepository->create($input);
        $items->logo = fileUrl($items->logo);
        $items->contract = fileUrl($items->contract);

        return $this->sendResponse($items->toArray(), trans('flash.api.save_success', ['model' => 'Item']));
    }

    /**
     * @param int $id
     * @return Response
     *
     * @SWG\Get(
     *      path="/items/{id}",
     *      summary="Display the specified Item",
     *      tags={"Item"},
     *      description="Get Item",
     *      produces={"application/json"},
     *      @SWG\Parameter(
     *          name="id",
     *          description="id of Item",
     *          type="integer",
     *          required=true,
     *          in="path"
     *      ),
     *      @SWG\Response(
     *          response=200,
     *          description="successful operation",
     *          @SWG\Schema(
     *              type="object",
     *              @SWG\Property(
     *                  property="success",
     *                  type="boolean"
     *              ),
     *              @SWG\Property(
     *                  property="data",
     *                  ref="#/definitions/Item"
     *              ),
     *              @SWG\Property(
     *                  property="message",
     *                  type="string"
     *              )
     *          )
     *      )
     * )
     */
    public function show($id)
    {
        /** @var Item $item */
        $item = $this->itemRepository->findWithoutFail($id);

        if (empty($item)) {
            return $this->sendError(trans('flash.api.not_found', ['model' => 'Item']), 404);
        }

        $item->logo = fileUrl($item->logo);
        $item->contract = fileUrl($item->contract);

        return $this->sendResponse($item->toArray(), trans('flash.api.retrieve_success', ['model' => 'Item']));
    }

    /**
     * @param int $id
     * @param UpdateItemAPIRequest $request
     * @return Response
     *
     * @SWG\Put(
     *      path="/items/{id}",
     *      summary="Update the specified Item in storage",
     *      tags={"Item"},
     *      description="Update Item",
     *      produces={"application/json"},
     *      @SWG\Parameter(
     *          name="id",
     *          description="id of Item",
     *          type="integer",
     *          required=true,
     *          in="path"
     *      ),
     *      @SWG\Parameter(
     *          name="body",
     *          in="body",
     *          description="Item that should be updated",
     *          required=false,
     *          @SWG\Schema(ref="#/definitions/Item")
     *      ),
     *      @SWG\Response(
     *          response=200,
     *          description="successful operation",
     *          @SWG\Schema(
     *              type="object",
     *              @SWG\Property(
     *                  property="success",
     *                  type="boolean"
     *              ),
     *              @SWG\Property(
     *                  property="data",
     *                  ref="#/definitions/Item"
     *              ),
     *              @SWG\Property(
     *                  property="message",
     *                  type="string"
     *              )
     *          )
     *      )
     * )
     */
    public function update($id, UpdateItemAPIRequest $request)
    {
        $input = $request->all();
        if (isset($input['logo']) && ! fileUrlExists($input['logo']))
        {
            return $this->sendError('图片不存在');
        }

        if (isset($input['contract']) && ! fileUrlExists($input['contract']))
        {
            return $this->sendError('合同 PDF 不存在');
        }

        if ( ! empty($input['contracts']))
        {
            foreach ($input['contracts'] as $val)
            {
                if (! fileUrlExists($val['photo']))
                {
                    return $this->sendError('合同图片不存在');
                }
            }
        }

        /** @var Item $item */
        $item = $this->itemRepository->findWithoutFail($id);

        if (empty($item)) {
            return $this->sendError(trans('flash.api.not_found', ['model' => 'Item']), 404);
        }

        $item = $this->itemRepository->update($input, $id);
        $item->logo = fileUrl($item->logo);
        $item->contract = fileUrl($item->contract);


        return $this->sendResponse($item->toArray(), trans('flash.api.update_success', ['model' => 'Item']));
    }

    /**
     * @param int $id
     * @return Response
     *
     * @SWG\Delete(
     *      path="/items/{id}",
     *      summary="Remove the specified Item from storage",
     *      tags={"Item"},
     *      description="Delete Item",
     *      produces={"application/json"},
     *      @SWG\Parameter(
     *          name="id",
     *          description="id of Item",
     *          type="integer",
     *          required=true,
     *          in="path"
     *      ),
     *      @SWG\Response(
     *          response=200,
     *          description="successful operation",
     *          @SWG\Schema(
     *              type="object",
     *              @SWG\Property(
     *                  property="success",
     *                  type="boolean"
     *              ),
     *              @SWG\Property(
     *                  property="data",
     *                  type="string"
     *              ),
     *              @SWG\Property(
     *                  property="message",
     *                  type="string"
     *              )
     *          )
     *      )
     * )
     */
    public function destroy($id)
    {
        /** @var Item $item */
        $item = $this->itemRepository->findWithoutFail($id);

        if (empty($item)) {
            return $this->sendError(trans('flash.api.not_found', ['model' => 'Item']), 404);
        }

        $item->delete();

        return $this->sendResponse($id, trans('flash.api.delete_success', ['model' => 'Item']));
    }

    public function indexOrders($id, Request $request, ItemOrderRepository $itemOrderRepo)
    {
        try {
            $session = $this->checkWeachtMiniProgramLogin($request);
        } catch (\Exception $e) {
            return $this->sendError($e->getMessage(), 401);
        }

        $item = $this->itemRepository->findWithoutFail($id);
        if (empty($item)) {
            return $this->sendError(trans('flash.api.not_found', ['model' => 'Item']), 404);
        }

        $itemOrders = $itemOrderRepo->getUserOrdersForItem($id, $request->all());
        $itemOrderRepo->resetUnread($id);
        return $this->sendResponse($itemOrders, trans('flash.api.retrieve_success', ['model' => 'Item Orders']));
    }

    public function showOrder($id, $orderId, Request $request, ItemOrderRepository $itemOrderRepo)
    {
        try {
            $session = $this->checkWeachtMiniProgramLogin($request);
        } catch (\Exception $e) {
            return $this->sendError($e->getMessage(), 401);
        }

        $item = $this->itemRepository->findWithoutFail($id);
        if (empty($item)) {
            return $this->sendError(trans('flash.api.not_found', ['model' => 'Item']), 404);
        }

        $itemOrder = $itemOrderRepo->findWithoutFail($orderId);
        if (empty($itemOrder)) {
            return $this->sendError(trans('flash.api.not_found', ['model' => 'Item Order']), 404);
        }

        $order = $itemOrderRepo->getUserOrderForItem($orderId, $id, $request->all());
        return $this->sendResponse($order->toArray(), trans('flash.api.retrieve_success', ['model' => 'Item Order']));
    }

    public function indexChannels($id, Request $request, ChannelRepository $channelRepo)
    {
        try {
            $session = $this->checkWeachtMiniProgramLogin($request);
        } catch (\Exception $e) {
            return $this->sendError($e->getMessage(), 401);
        }

        $item = $this->itemRepository->findWithoutFail($id);
        if (empty($item)) {
            return $this->sendError(trans('flash.api.not_found', ['model' => 'Item']), 404);
        }

        $channels = $channelRepo->getChannelsForItem($id, $request->all());
        return $this->sendResponse($channels->toArray(), trans('flash.api.retrieve_success', ['model' => 'Item']));
    }

    public function showChannel($id, $channelId, Request $request, ChannelRepository $channelRepo)
    {
        try {
            $session = $this->checkWeachtMiniProgramLogin($request);
        } catch (\Exception $e) {
            return $this->sendError($e->getMessage(), 401);
        }

        $item = $this->itemRepository->findWithoutFail($id);
        if (empty($item)) {
            return $this->sendError(trans('flash.api.not_found', ['model' => 'Item']), 404);
        }

        $channel = $channelRepo->findWithoutFail($channelId);
        if (empty($channel)) {
            return $this->sendError(trans('flash.api.not_found', ['model' => 'Channel']), 404);
        }

        $channel = $channelRepo->getChannelForItem($channelId, $id, $request->all());
        return $this->sendResponse($channel->toArray(), trans('flash.api.retrieve_success', ['model' => 'Item']));
    }

    public function indexChannelUsers($id, $channelId, Request $request,
        ChannelRepository $channelRepo,
        ItemOrderRepository $itemOrderRepo)
    {
        try {
            $session = $this->checkWeachtMiniProgramLogin($request);
        } catch (\Exception $e) {
            return $this->sendError($e->getMessage(), 401);
        }

        $item = $this->itemRepository->findWithoutFail($id);
        if (empty($item)) {
            return $this->sendError(trans('flash.api.not_found', ['model' => 'Item']), 404);
        }

        $channel = $channelRepo->findWithoutFail($channelId);
        if (empty($channel)) {
            return $this->sendError(trans('flash.api.not_found', ['model' => 'Channel']), 404);
        }

        $users = $itemOrderRepo->getChannelUsersForItem($id, $channelId, $request->all());
        return $this->sendResponse($users, trans('flash.api.retrieve_success', ['model' => 'Item Orders']));
    }

    public function storeManagers($id,
        CreateItemManagerAPIRequest $request,
        WechatUserRepository $wechatUserRepo,
        ItemManagerRepository $itemManagerRepo)
    {
        $item = $this->itemRepository->findWithoutFail($id);
        if (empty($item)) {
            return $this->sendError(trans('flash.api.not_found', ['model' => 'Item']), 404);
        }

        $input = $request->all();
        $user = $wechatUserRepo->getUserByUnionid($input['unionid']);
        if (empty($user)) {
            return $this->sendError(trans('flash.api.not_found', ['model' => 'Wechat User']), 404);
        }

        $exists = $itemManagerRepo->getManagerByWechatUserId($user->id);
        if ( ! empty($exists))
        {
            return $this->sendError('该账号已绑定项目方管理员', 422);
        }

        $manager = $itemManagerRepo->create(['item_id' => $id, 'wechat_user_id' => $user->id]);
        return $this->sendResponse($manager->toArray(), trans('flash.api.save_success', ['model' => 'Item Manager']));
    }

    public function destroyManagers($id, $unionid,
        WechatUserRepository $wechatUserRepo,
        ItemManagerRepository $itemManagerRepo)
    {
        $channel = $this->itemRepository->findWithoutFail($id);
        if (empty($channel)) {
            return $this->sendError(trans('flash.api.not_found', ['model' => 'Item']), 404);
        }

        $user = $wechatUserRepo->getUserByUnionid($unionid);
        if (empty($user)) {
            return $this->sendError(trans('flash.api.not_found', ['model' => 'Wechat User']), 404);
        }

        $manager = $itemManagerRepo->getManagerByItemIdAndWechatUserId($id, $user->id);
        if (empty($manager))
        {
            return $this->sendError('该账号未绑定该项目方管理员', 422);
        }

        $manager->forceDelete();

        return $this->sendResponse($id, trans('flash.api.delete_success', ['model' => 'Item Manager']));
    }

    public function storeChannelCooperations($id, $channelId, Request $request, ChannelRepository $channelRepo, CooperationRepository $cooperationRepo)
    {
        try {
            $session = $this->checkWeachtMiniProgramLogin($request);
        } catch (\Exception $e) {
            return $this->sendError($e->getMessage(), 401);
        }

        $item = $this->itemRepository->findWithoutFail($id);
        if (empty($item)) {
            return $this->sendError(trans('flash.api.not_found', ['model' => 'Item']), 404);
        }

        $channel = $channelRepo->findWithoutFail($channelId);
        if (empty($channel)) {
            return $this->sendError(trans('flash.api.not_found', ['model' => 'Channel']), 404);
        }

        $cooperation = $cooperationRepo->getByChannelIdAndItemId($channelId, $id);
        if ($cooperation)
        {
            if ($cooperation->apply_from == Cooperation::APPLY_FROM_ITEM)
            {
                return $this->sendError('已提交过合作申请');
            }
            else
            {
                return $this->sendError('渠道已提交过合作申请');
            }
        }

        $input = [
            'channel_id' => $channelId,
            'item_id' => $id,
            'apply_from' => Cooperation::APPLY_FROM_ITEM
        ];
        $cooperations = $cooperationRepo->create($input);
        return $this->sendResponse($cooperations->toArray(), trans('flash.api.save_success', ['model' => 'Cooperation']));
    }

    public function updateChannelCooperations($id, $channelId, Request $request, ChannelRepository $channelRepo, CooperationRepository $cooperationRepo)
    {
        try {
            $session = $this->checkWeachtMiniProgramLogin($request);
        } catch (\Exception $e) {
            return $this->sendError($e->getMessage(), 401);
        }

        $item = $this->itemRepository->findWithoutFail($id);
        if (empty($item)) {
            return $this->sendError(trans('flash.api.not_found', ['model' => 'Item']), 404);
        }

        $channel = $channelRepo->findWithoutFail($channelId);
        if (empty($channel)) {
            return $this->sendError(trans('flash.api.not_found', ['model' => 'Channel']), 404);
        }

        $cooperation = $cooperationRepo->getByChannelIdAndItemId($channelId, $id);
        if ( ! $cooperation || $cooperation->apply_from == Cooperation::APPLY_FROM_ITEM)
        {
            return $this->sendError('该项目方未提交过合作申请');
        }
        elseif ($cooperation->status != Cooperation::STATUS_DEFAULT)
        {
            return $this->sendError('该请求已经处理');
        }

        if ($request->input('agree', 0))
        {
            $cooperation->status = Cooperation::STATUS_SUCCESS;
            $cooperation->save();

            return $this->sendResponse($cooperation->toArray(), trans('flash.api.save_success', ['model' => 'Cooperation']));
        }
        elseif ($request->input('refused', 0))
        {
            $cooperation->forceDelete();
            return $this->sendResponse([], '拒绝合作成功');
        }

        return $this->sendError('参数有误');
    }
}
